﻿﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Globalization;

namespace DownloadTool
{
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        private const int ThreadCount = 4;
        private string _downloadingTabHeader;
        private string _completedTabHeader;
        
        public ObservableCollection<DownloadTask> DownloadingTasks { get; set; }
        public ObservableCollection<DownloadTask> CompletedTasks { get; set; }

        public bool HasDownloadingTasks => !DownloadingTasks.Any();
        public bool HasCompletedTasks => !CompletedTasks.Any();
        
        public string DownloadingTabHeader
        {
            get => _downloadingTabHeader;
            set
            {
                _downloadingTabHeader = value;
                OnPropertyChanged(nameof(DownloadingTabHeader));
            }
        }
        
        public string CompletedTabHeader
        {
            get => _completedTabHeader;
            set
            {
                _completedTabHeader = value;
                OnPropertyChanged(nameof(CompletedTabHeader));
            }
        }

        public MainWindow()
        {
            InitializeComponent();
            DownloadingTasks = new ObservableCollection<DownloadTask>();
            CompletedTasks = new ObservableCollection<DownloadTask>();
            
            DataContext = this;
            
            // 初始化Tab标题
            UpdateTabHeaders();
            
            // 当集合变化时更新Tab标题
            DownloadingTasks.CollectionChanged += (s, e) => {
                OnPropertyChanged(nameof(HasDownloadingTasks));
                UpdateTabHeaders();
                SaveTasks(); // Save tasks when collection changes
            };
            CompletedTasks.CollectionChanged += (s, e) => {
                OnPropertyChanged(nameof(HasCompletedTasks));
                UpdateTabHeaders();
                SaveTasks(); // Save tasks when collection changes
            };
            
            // Load saved tasks
            LoadSavedTasks();
            
            // Save tasks when application closes
            Closing += (s, e) => {
                SaveTasks();
            };
        }
        
        private void LoadSavedTasks()
        {
            var taskData = TaskPersistence.Instance.LoadTasks();
            
            // Load completed tasks
            foreach (var task in taskData.CompletedTasks)
            {
                // Only add tasks that aren't already in the CompletedTasks collection
                if (!CompletedTasks.Any(t => t.Id == task.Id))
                {
                    CompletedTasks.Add(task);
                }
            }
            
            // Load downloading tasks
            foreach (var task in taskData.DownloadingTasks)
            {
                // Only add tasks that aren't already in the DownloadingTasks collection
                if (!DownloadingTasks.Any(t => t.Id == task.Id))
                {
                    DownloadingTasks.Add(task);
                    
                    // Restart download for tasks that were in progress
                    if (task.Status != "已暂停" && task.Status != "已取消")
                    {
                        task.Status = "准备中";
                        _ = Task.Run(async () => await StartDownload(task));
                    }
                }
            }
        }
        
        private void SaveTasks()
        {
            // Explicitly save tasks to ensure they're persisted
            TaskPersistence.Instance.SaveTasks(DownloadingTasks, CompletedTasks);
        }

        private void NewDownloadButton_Click(object sender, RoutedEventArgs e)
        {
            var dialog = new NewDownloadDialog();
            dialog.Owner = this;
            
            if (dialog.ShowDialog() == true)
            {
                var task = new DownloadTask
                {
                    Url = dialog.DownloadUrl,
                    SavePath = AppSettings.Instance.DefaultDownloadPath,
                    Status = "准备中"
                };
                
                DownloadingTasks.Add(task);
                
                    // Save tasks
                    SaveTasks();
                
                // Switch to the Downloading tab
                MainTabControl.SelectedIndex = 0; // Index 0 is the Downloading tab
                
                // Start download in background
                _ = Task.Run(async () => await StartDownload(task));
            }
        }
        
        private void SettingsButton_Click(object sender, RoutedEventArgs e)
        {
            var dialog = new SimpleSettingsDialog();
            dialog.Owner = this;
            dialog.ShowDialog();
        }

        private async Task StartDownload(DownloadTask task)
        {
            try
            {
                await Dispatcher.InvokeAsync(() => task.Status = "正在获取文件信息...");
                
                using var client = new HttpClient();
                var response = await client.SendAsync(new HttpRequestMessage(HttpMethod.Head, task.Url), task.CancellationTokenSource.Token);
                
                if (!response.IsSuccessStatusCode)
                {
                    await Dispatcher.InvokeAsync(() => task.Status = "无法获取文件信息");
                    return;
                }

                string fileName = GetFileNameFromResponse(response, task.Url);
                string fullPath = Path.Combine(task.SavePath, fileName);
                
                await Dispatcher.InvokeAsync(() => {
                    task.FileName = fileName;
                    task.FilePath = fullPath;
                });

                if (response.Content.Headers.ContentLength.HasValue)
                {
                    long fileSize = response.Content.Headers.ContentLength.Value;
                    await Dispatcher.InvokeAsync(() => task.TotalBytes = fileSize);
                    await DownloadFileMultiThread(task, fileSize);
                }
                else
                {
                    await DownloadFileSingleThread(task);
                }
            }
            catch (OperationCanceledException)
            {
                await Dispatcher.InvokeAsync(() => task.Status = "已取消");
            }
            catch (Exception ex)
            {
                await Dispatcher.InvokeAsync(() => task.Status = $"下载失败: {ex.Message}");
            }
        }

        private async Task DownloadFileMultiThread(DownloadTask task, long fileSize)
        {
            string tempDir = Path.Combine(task.SavePath, "_tmp_" + task.Id);
            Directory.CreateDirectory(tempDir);

            try
            {
                long partSize = fileSize / ThreadCount;
                var tasks = new Task[ThreadCount];
                var progressArr = new long[ThreadCount];

                for (int i = 0; i < ThreadCount; i++)
                {
                    long start = i * partSize;
                    long end = (i == ThreadCount - 1) ? fileSize - 1 : (start + partSize - 1);
                    int partIdx = i;

                    tasks[i] = Task.Run(async () =>
                    {
                        using var partClient = new HttpClient();
                        var req = new HttpRequestMessage(HttpMethod.Get, task.Url);
                        req.Headers.Range = new System.Net.Http.Headers.RangeHeaderValue(start, end);
                        
                        using var partResp = await partClient.SendAsync(req, HttpCompletionOption.ResponseHeadersRead, task.CancellationTokenSource.Token);
                        partResp.EnsureSuccessStatusCode();
                        
                        string partPath = Path.Combine(tempDir, $"part_{partIdx}");
                        using var fs = new FileStream(partPath, FileMode.Create, FileAccess.Write, FileShare.None);
                        using var stream = await partResp.Content.ReadAsStreamAsync();
                        
                        byte[] buffer = new byte[8192];
                        int read;
                        while ((read = await stream.ReadAsync(buffer, 0, buffer.Length, task.CancellationTokenSource.Token)) > 0)
                        {
                            // 检查是否暂停
                            while (task.IsPaused)
                            {
                                await Task.Delay(500); // 暂停时等待
                                if (task.CancellationTokenSource.Token.IsCancellationRequested)
                                    break;
                            }
                            
                            await fs.WriteAsync(buffer, 0, read, task.CancellationTokenSource.Token);
                            Interlocked.Add(ref progressArr[partIdx], read);
                            UpdateTaskProgress(task, progressArr);
                        }
                    }, task.CancellationTokenSource.Token);
                }

                await Dispatcher.InvokeAsync(() => {
                    task.Status = "正在下载...";
                    task.IsPaused = false;
                });
                await Task.WhenAll(tasks);

                await Dispatcher.InvokeAsync(() => task.Status = "正在合并文件...");
                
                using var outFs = new FileStream(task.FilePath, FileMode.Create, FileAccess.Write);
                for (int i = 0; i < ThreadCount; i++)
                {
                    string partPath = Path.Combine(tempDir, $"part_{i}");
                    using var partFs = new FileStream(partPath, FileMode.Open, FileAccess.Read);
                    await partFs.CopyToAsync(outFs, task.CancellationTokenSource.Token);
                }

                await Dispatcher.InvokeAsync(() => {
                    task.Progress = 100;
                    task.Status = "下载完成";
                    task.CompletedTime = DateTime.Now;
                    
                    DownloadingTasks.Remove(task);
                    CompletedTasks.Add(task);
                    
                    // Tasks are automatically saved when collection changes
                });
            }
            finally
            {
                if (Directory.Exists(tempDir))
                {
                    Directory.Delete(tempDir, true);
                }
            }
        }

        private async Task DownloadFileSingleThread(DownloadTask task)
        {
            using var client = new HttpClient();
            using var response = await client.GetAsync(task.Url, HttpCompletionOption.ResponseHeadersRead, task.CancellationTokenSource.Token);
            response.EnsureSuccessStatusCode();

            await Dispatcher.InvokeAsync(() => task.Status = "正在下载...");

            using var stream = await response.Content.ReadAsStreamAsync();
            using var fileStream = new FileStream(task.FilePath, FileMode.Create, FileAccess.Write, FileShare.None);

            byte[] buffer = new byte[8192];
            int bytesRead;

            while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, task.CancellationTokenSource.Token)) > 0)
            {
                // 检查是否暂停
                while (task.IsPaused)
                {
                    await Task.Delay(500); // 暂停时等待
                    if (task.CancellationTokenSource.Token.IsCancellationRequested)
                        break;
                }
                
                await fileStream.WriteAsync(buffer, 0, bytesRead, task.CancellationTokenSource.Token);
                
                await Dispatcher.InvokeAsync(() => {
                    task.DownloadedBytes += bytesRead;
                    if (task.TotalBytes > 0)
                    {
                        task.Progress = (double)task.DownloadedBytes / task.TotalBytes * 100;
                    }
                });
            }

            await Dispatcher.InvokeAsync(() => {
                task.Progress = 100;
                task.Status = "下载完成";
                task.CompletedTime = DateTime.Now;
                
                DownloadingTasks.Remove(task);
                CompletedTasks.Add(task);
            });
        }

        private void UpdateTaskProgress(DownloadTask task, long[] progressArr)
        {
            long downloaded = progressArr.Sum();
            double percent = (double)downloaded / task.TotalBytes * 100;
            
            Dispatcher.InvokeAsync(() => {
                task.DownloadedBytes = downloaded;
                task.Progress = percent;
            });
        }

        private string GetFileNameFromResponse(HttpResponseMessage response, string url)
        {
            if (response.Content.Headers.ContentDisposition?.FileName != null)
            {
                string fileName = response.Content.Headers.ContentDisposition.FileName.Trim('"');
                if (!string.IsNullOrWhiteSpace(fileName))
                    return fileName;
            }

            try
            {
                Uri uri = new Uri(url);
                string[] segments = uri.Segments;

                for (int i = segments.Length - 1; i >= 0; i--)
                {
                    string segment = segments[i].TrimEnd('/');
                    if (!string.IsNullOrWhiteSpace(segment) && segment.Contains('.'))
                    {
                        return segment;
                    }
                }

                for (int i = segments.Length - 1; i >= 0; i--)
                {
                    string segment = segments[i].TrimEnd('/');
                    if (!string.IsNullOrWhiteSpace(segment))
                    {
                        return segment;
                    }
                }
            }
            catch { }

            try
            {
                string pathFileName = Path.GetFileName(new Uri(url).LocalPath);
                if (!string.IsNullOrWhiteSpace(pathFileName))
                    return pathFileName;
            }
            catch { }

            return "downloaded_file";
        }

        private void PauseResumeDownload_Click(object sender, RoutedEventArgs e)
        {
            if (sender is System.Windows.Controls.Button button && button.Tag is DownloadTask task)
            {
                if (task.IsPaused)
                {
                    // 恢复下载
                    task.IsPaused = false;
                    task.Status = "正在下载...";
                    // 这里需要实现恢复下载的逻辑
                    // 由于示例中没有实现真正的暂停/恢复机制，这里只是状态切换
                    
                    // Save tasks
                    SaveTasks();
                }
                else
                {
                    // 暂停下载
                    task.IsPaused = true;
                    task.Status = "已暂停";
                    // 这里需要实现暂停下载的逻辑
                    // 由于示例中没有实现真正的暂停/恢复机制，这里只是状态切换
                    
                    // Save tasks
                    SaveTasks();
                }
            }
        }
        
        private void DeleteDownload_Click(object sender, RoutedEventArgs e)
        {
            if (sender is System.Windows.Controls.Button button && button.Tag is DownloadTask task)
            {
                bool result = ConfirmDialog.Show(this, "确认删除", "确定要删除此下载任务吗？", "question");
                
                if (result)
                {
                    task.CancellationTokenSource.Cancel();
                    DownloadingTasks.Remove(task);
                    
                    // Mark as cancelled
                    task.Status = "已取消";
                    // Tasks are automatically saved when collection changes
                }
            }
        }

        private void OpenFile_Click(object sender, RoutedEventArgs e)
        {
            if (sender is System.Windows.Controls.Button button && button.Tag is DownloadTask task)
            {
                try
                {
                    if (File.Exists(task.FilePath))
                    {
                        Process.Start(new ProcessStartInfo
                        {
                            FileName = task.FilePath,
                            UseShellExecute = true
                        });
                    }
                    else
                    {
                        System.Windows.MessageBox.Show("文件不存在。", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                }
                catch (Exception ex)
                {
                    System.Windows.MessageBox.Show($"无法打开文件: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        private void DeleteTask_Click(object sender, RoutedEventArgs e)
        {
            if (sender is System.Windows.Controls.Button button && button.Tag is DownloadTask task)
            {
                bool result = ConfirmDialog.Show(this, "确认删除", "确定要删除此任务吗？", "question");
                
                if (result)
                {
                    CompletedTasks.Remove(task);
                    
                    // Tasks are automatically saved when collection changes
                }
            }
        }
        
        private void OpenDirectory_Click(object sender, RoutedEventArgs e)
        {
            if (sender is System.Windows.Controls.Button button && button.Tag is DownloadTask task)
            {
                try
                {
                    string directory = Path.GetDirectoryName(task.FilePath);
                    if (Directory.Exists(directory))
                    {
                        Process.Start(new ProcessStartInfo
                        {
                            FileName = directory,
                            UseShellExecute = true
                        });
                    }
                    else
                    {
                        System.Windows.MessageBox.Show("目录不存在。", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                }
                catch (Exception ex)
                {
                    System.Windows.MessageBox.Show($"无法打开目录: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        public event PropertyChangedEventHandler? PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        
        private void UpdateTabHeaders()
        {
            DownloadingTabHeader = $"下载中({DownloadingTasks.Count})";
            CompletedTabHeader = $"已完成({CompletedTasks.Count})";
        }
        
    }
}